package org.movee.net.cfg.parser.antlr;

import org.movee.net.cfg.parser.parser.xorplus.XorplusBgpParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusBgpPeerParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusConfigContext;
import org.movee.net.cfg.parser.parser.xorplus.XorplusConfigModel;
import org.movee.net.cfg.parser.parser.xorplus.XorplusConfigEntityType;
import org.movee.net.cfg.parser.parser.xorplus.XorplusConfigNode;
import org.movee.net.cfg.parser.parser.xorplus.XorplusInterfaceType;
import org.movee.net.cfg.parser.parser.xorplus.XorplusIntfParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusSystemParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusVlanIntfIpParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusVlanIntfParser;
import org.movee.net.cfg.parser.parser.xorplus.XorplusVlanParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

/**
 *
 *
 * @author 
 */
@Slf4j
public class XorplusCfgListenerImpl extends XorplusCfgBaseListener {

    private XorplusConfigNode currCfgNode = null;
    private final XorplusConfigContext context;
    private final XorplusSystemParser systemParser = new XorplusSystemParser();
    private final XorplusIntfParser intfParser = new XorplusIntfParser();
    private final XorplusVlanIntfParser vlanIntfParser = new XorplusVlanIntfParser();
    private final XorplusVlanIntfIpParser ipParser = new XorplusVlanIntfIpParser();
    private final XorplusVlanParser vlanParser = new XorplusVlanParser();
    private final XorplusBgpParser bgpParser = new XorplusBgpParser();
    private final XorplusBgpPeerParser bgpPeerParser = new XorplusBgpPeerParser();
    private final ObjectMapper jacksonMapper = new ObjectMapper();

    public XorplusCfgListenerImpl(String mgmtIp, String vendor) {
        this.context = new XorplusConfigContext(mgmtIp, vendor);
        this.currCfgNode = createRootConfigNode(context);
    }

    public XorplusConfigModel getModel() {
        return context.getModel();
    }

    @Override
    public void enterFile(XorplusCfgParser.FileContext ctx) {
        super.enterFile(ctx);
    }

    @Override
    public void exitFile(XorplusCfgParser.FileContext ctx) {
        super.exitFile(ctx);
    }

    @Override
    public void enterStatement(XorplusCfgParser.StatementContext ctx) {

        String originWord0 = ctx.word(0) == null ? "" : ctx.word(0).getText();

        String word0 = normKeyword(originWord0);
        String word1 = parseArgumentContent(ctx.word(1));

        XorplusConfigNode cfgNode = createConfigNode(currCfgNode, word0, word1);
        switch (cfgNode.getEntityType()) {
            case SYSTEM: {
                systemParser.parse(cfgNode);
                break;
            }
            case INTERFACE: {
                intfParser.parse(cfgNode);
                break;
            }
            case VLAN_INTERFACE: {
                vlanIntfParser.parse(cfgNode);
                break;
            }
            case VLAN_INTERFACE_IP: {
                ipParser.parse(cfgNode);
                break;
            }
            case VLAN: {
                vlanParser.parse(cfgNode);
                break;
            }
            case BGP: {
                bgpParser.parse(cfgNode);
                break;
            }
            case BGP_PEER: {
                bgpPeerParser.parse(cfgNode);
                break;
            }
            default: {

            }
        }

        currCfgNode = cfgNode;
        // log.info("==keyword text: {}", keywordText);
    }

    @Override
    public void exitStatement(XorplusCfgParser.StatementContext ctx) {
        if (currCfgNode.getIsEntityRoot()) {
            XorplusConfigContext context = currCfgNode.getContext();
            XorplusConfigModel model = context.getModel();
            XorplusConfigEntityType type = currCfgNode.getEntityType();
            Object entityInstance = context.remParsingEntity(type);
            switch (type) {
                case VLAN_INTERFACE: {
                    XorplusConfigModel.VlanInterface vlanIntf = (XorplusConfigModel.VlanInterface) entityInstance;
                    model.putVlanIntf(vlanIntf.getName(), vlanIntf);
                    break;
                }
                case INTERFACE: {
                    XorplusConfigModel.Interface intf = (XorplusConfigModel.Interface) entityInstance;
                    model.putIntf(intf.getName(), intf);
                    break;
                }
                case VLAN_INTERFACE_IP: {
                    XorplusConfigModel.VlanInterface vlanIntf = (XorplusConfigModel.VlanInterface) context.getParsingEntity(XorplusConfigEntityType.VLAN_INTERFACE);
                    vlanIntf.getIntfIps().add((XorplusConfigModel.VlanInterfaceIp) entityInstance);
                    break;
                }
                case VLAN: {
                    XorplusConfigModel.Vlan vlan = (XorplusConfigModel.Vlan) entityInstance;
                    model.putVlan(vlan.getVlanId(), vlan);
                    break;
                }
                case BGP: {
                    XorplusConfigModel.Bgp bgp = (XorplusConfigModel.Bgp) entityInstance;
                    model.setBgp(bgp);
                    break;
                }
                case BGP_PEER: {
                    XorplusConfigModel.Bgp bgp = (XorplusConfigModel.Bgp) context.getParsingEntity(XorplusConfigEntityType.BGP);
                    XorplusConfigModel.BgpPeer bgpPeer = (XorplusConfigModel.BgpPeer) entityInstance;
                    bgp.getPeers().put(bgpPeer.getPeerIp(), bgpPeer);
                    break;
                }
                default: {
                    //
                }
            }
        }

        currCfgNode = currCfgNode.getParent();
    }

    private String getQuotedStringContent(String quotedStr) {
        if (StringUtils.hasLength(quotedStr) && quotedStr.length() >= 2) {
            return quotedStr.substring(1, quotedStr.length() - 1);
        }
        return "";
    }

    private String parseArgumentContent(XorplusCfgParser.WordContext ctx) {
        String content = "";
        if (ctx != null) {
            if (ctx.SQUOTE_STRING() != null) {
                String quotedStr = ctx.SQUOTE_STRING().getText();
                content = getQuotedStringContent(quotedStr);
            } else if (ctx.DQUOTE_STRING() != null) {
                String quotedStr = ctx.DQUOTE_STRING().getText();
                content = getQuotedStringContent(quotedStr);
            } else if (ctx.WORD() != null) {
                content = ctx.WORD().getText();
            }

        }

        return content;
    }

    private String normKeyword(String origin) {
        if (StringUtils.hasLength(origin) && origin.charAt(origin.length() - 1) == ':') {
            return origin.substring(0, origin.length() - 1);
        }

        return origin;
    }

    private XorplusConfigNode createConfigNode(XorplusConfigNode parent, String word0, String word1) {
        XorplusConfigNode cfgNode = new XorplusConfigNode();
        cfgNode.setParent(parent);
        cfgNode.setWord0(word0);
        cfgNode.setWord1(word1);
        cfgNode.setIsRoot(false);
        cfgNode.setContext(parent.getContext());

        if ("system".equals(word0) && parent.getIsRoot()) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.SYSTEM);
        } else if ("interface".equals(word0) && parent.getIsRoot()) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.INTERFACES);
        } else if ("vlan-interface".equals(word0) && parent.getIsRoot()) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.VLAN_INTERFACES);
        } else if ("vlan".equals(word0) && parent.getIsRoot()) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.VLANS);
        } else if ("bgp".equals(word0)
                && "protocols".equals(parent.getWord0())
                && parent.getParent() != null
                && parent.getParent().getIsRoot()) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.BGP);
        } else if ("peer".equals(word0)
                && parent.getIsEntityRoot()
                && parent.getEntityType() == XorplusConfigEntityType.BGP) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.BGP_PEER);
        } else if (parent.getIsEntityRoot() && parent.getEntityType() == XorplusConfigEntityType.INTERFACES) {
            XorplusInterfaceType intfType = XorplusInterfaceType.fromName(word0);
            if (intfType != null) {
                cfgNode.setIsEntityRoot(true);
                cfgNode.setEntityType(XorplusConfigEntityType.INTERFACE);
            } else {
                log.warn("not supported interface name: {}", word0);
                cfgNode.setIsEntityRoot(false);
                cfgNode.setEntityType(XorplusConfigEntityType.UNKNOWN);
            }
        } else if ("interface".equals(word0)
                && parent.getIsEntityRoot()
                && parent.getEntityType() == XorplusConfigEntityType.VLAN_INTERFACES) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.VLAN_INTERFACE);
        } else if ("address".equals(word0)
                && parent.getIsEntityRoot()
                && parent.getEntityType() == XorplusConfigEntityType.VLAN_INTERFACE) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.VLAN_INTERFACE_IP);
        } else if ("vlan-id".equals(word0)
                && parent.getIsEntityRoot()
                && parent.getEntityType() == XorplusConfigEntityType.VLANS) {
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.VLAN);
        } else if (parent.getIsRoot()) {
            // 暂不支持解析的一级节点
            cfgNode.setIsEntityRoot(true);
            cfgNode.setEntityType(XorplusConfigEntityType.UNKNOWN);
        } else {
            // 支持解析或不支持解析的非根节点
            cfgNode.setIsEntityRoot(false);
            // 继承父节点的
            cfgNode.setEntityType(parent.getEntityType());
        }

        return cfgNode;
    }

    private XorplusConfigNode createRootConfigNode(XorplusConfigContext context) {
        XorplusConfigNode cfgNode = new XorplusConfigNode();
        cfgNode.setParent(null);
        cfgNode.setWord0("root");
        cfgNode.setWord1("root");
        cfgNode.setIsRoot(true);
        cfgNode.setIsEntityRoot(false);
        cfgNode.setEntityType(XorplusConfigEntityType.ROOT);
        cfgNode.setContext(context);
        return cfgNode;
    }
}
